package com.redhat.auth.log.core;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import org.hibernate.criterion.DetachedCriteria;
import com.dayatang.domain.InstanceFactory;
import com.redhat.auth.log.common.CacheDataValue;
import com.redhat.auth.log.common.LogDescriptionBean;
import com.redhat.auth.log.core.domain.BizLogInfo;
import com.redhat.auth.log.query.LogQueryChannelImpl;

/**
 * 日志功能后半部分，后半部分功能交给线程来管理，避免过分占用时间
 * 
 * @author lingen.liu
 * 
 */
public class LogAnalysisSuccess implements Runnable {

	//存储值有五大来源，前值，后值，参数值，返回值以及类属性值
	private CacheDataValue cacheDataValue;

	// 日志查询通道，用来查询后值
	private static LogQueryChannelImpl logQueryChannel;

	// hibernate查询对象，前值就是使用此值查询出来，后值用同样的值查询同样的对象，以获取改变情况
	private HashMap<Class, List<String>> criteriaMap;

	// 业务定义
	private LogDescriptionBean logBean;

	private LogBizQuery logBizSave;

	private BizLogInfo bizLogInfo;
	
	private String entityId;

	public LogAnalysisSuccess(LogDescriptionBean logBean,
			HashMap<Class, List<String>> criteriaMap,
			BizLogInfo bizLogInfo) {
		this.logBean = logBean;
		this.criteriaMap = criteriaMap;
		this.bizLogInfo = bizLogInfo;
	}
	
	public void initValue(CacheDataValue cacheDataValue){
		this.cacheDataValue =  cacheDataValue;
	}
	
	public void initEntityValue(HashMap<String,Object> keyValues){
		Set<String> entitySet = keyValues.keySet();
		StringBuffer entityBuffer = new StringBuffer();
		for(String key:entitySet){
			Object value = keyValues.get(key);
			if(value!=null)entityBuffer.append(key+"="+value.toString()+"<$CDATA$>");
		}
		this.entityId = entityBuffer.toString();
	}

	@Override
	public void run() {
		// 进行后值的查询
		Set<Class> criteriaSet = criteriaMap.keySet();
		HashMap<String, List> afterValue = new HashMap<String, List>();
		for (Class entity : criteriaSet) {
			List<String> criteria = criteriaMap.get(entity);
			List<Object> value = getLogQueryChannel().queryByCriteria(criteria);
			afterValue.put(entity.getSimpleName(), value);
			cacheDataValue.setAfterValues(afterValue);
		}
		String value = cacheDataValue.initValue(logBean.getRecordValues());
		
		//构造一个BizLogInfo对象
		//bizLogInfo.setEntityId(entityId);
		bizLogInfo.setBizDate(new Date());
		bizLogInfo.setBizOperation(logBean.getBizDescription());
		bizLogInfo.setBizType(logBean.getBizOperationType());
		bizLogInfo.setRecordValue(value);
		bizLogInfo.setResult("SUCCESS");
		getLogBizSave().add(bizLogInfo);
	}

	public static LogQueryChannelImpl getLogQueryChannel() {
		if (logQueryChannel == null)
			logQueryChannel = InstanceFactory
					.getInstance(LogQueryChannelImpl.class);
		return logQueryChannel;
	}

	public LogBizQuery getLogBizSave() {
		if (logBizSave == null)
			logBizSave = InstanceFactory.getInstance(LogBizQuery.class);
		return logBizSave;
	}
	
	/*

	private List<BizValue> getValueBean(HashMap<Class, Object> keyValues,
			HashMap<Class, List> beforeValues, HashMap<Class, List> afterValues) {
		List<BizValue> valueBeans = new ArrayList<BizValue>();
		Set<Class> keySet = keyValues.keySet();
		for (Class key : keySet) {
			BizValue bizValue = new BizValue();
			bizValue.setClassEntity(key.getSimpleName());
			bizValue.setFullClass(key.getName());
			String beforeXml = getValue(key, beforeValues.get(key));
			String afterXml = getValue(key, afterValues.get(key));
			if (!beforeXml.equals(afterXml)) {
				if (beforeValues.containsKey(key))
					bizValue.setBeforeValue(beforeXml);
				if (afterValues.containsKey(key))
					bizValue.setAfterValue(afterXml);
				valueBeans.add(bizValue);
			}
		}
		return valueBeans;
	}

	/*
	private String getValue(Class key, List<Object> valueList) {
		ValueBean valueBean = logBean.getValues().get(key);
		String[] propertiesRecord = valueBean.getRecordPropertiesValues();
		String[] relationRecord = valueBean.getRecordRelationValues();

		Document document = DocumentHelper.createDocument();
		Element log = document.addElement("Log");
		for (Object before : valueList) {
			Element rootElement = log.addElement(key.getSimpleName());
			for (String property : propertiesRecord) {
				Element element = rootElement.addElement(property);
				Object value = ObjectValueReflection.getReflectionValue(
						property, before);
				element.setText(value == null ? "" : value.toString());
			}

			HashMap<String, String[]> relationMap = parseRelationRecord(relationRecord);
			Set<String> relationKey = relationMap.keySet();

			for (String relation : relationKey) {
				Object relationValues = ObjectValueReflection
						.getReflectionValue(relation, before);
				String[] propertiesRelations = relationMap.get(relation);
				ArrayList relationList = new ArrayList();
				if (relationValues instanceof Collection) {
					Collection relationValueCollection = (Collection) relationValues;
					relationList.addAll(relationValueCollection);

				} else {
					relationList.add(relationValues);
				}
				for (Object realtionValue : relationList) {
					Element relationRoot = rootElement.addElement(relation);
					for (String property : propertiesRelations) {
						Element element = relationRoot.addElement(property);
						Object value = ObjectValueReflection
								.reflectObjectValueString(property,
										realtionValue);
						element.setText(value == null ? "" : value.toString());
					}
				}
			}
		}
		return document.asXML();
	}


	private HashMap<String, String[]> parseRelationRecord(String[] relations) {
		HashMap<String, String[]> relationMap = new HashMap<String, String[]>();
		for (String relation : relations) {
			if (relation == null || relation.trim().equals(""))
				continue;
			if (!relation.contains("[")) {
				throw new RuntimeException(
						"Not defined properies for relationship:" + relation);
			}
			String key = relation.substring(0, relation.indexOf("["));
			String value = relation.substring(relation.indexOf("[") + 1,
					relation.indexOf("]"));
			relationMap.put(key, value.split("\\,"));
		}
		return relationMap;
	}
	
	*/

}
